
const fs = require('fs');
const db = require('db');
const { formatMoney } = require('accounting');
const superagent = require('superagent');
const path = require('path');
const { v4 } = require('uuid');
const moment = require('moment');
const process = require("child_process");
const { encode } = require('js-base64');
const { toUpdate } = require('tools/sqlString');
const getAccessToken = require('tools/dd/getAccessToken');
const { sendMail } = require('nmailer');
const log = require('tools/log');

module.exports = async ctx => {
    const { connection, run, comply } = db.init();
    await run('BEGIN'); // 开始事务
    try {
        const id = ctx.params.id;
        const company = ctx.headers["company-id"];
        const access_token = await getAccessToken(company);
        const fileName = ctx.request.body.invoiceFile.fileName;
        const filePath = ctx.request.body.invoiceFile.filePath;
        const invoicePath = await rename(filePath, fileName)
        const invoiceFile = encode(invoicePath);
        await update(id, ctx, invoiceFile, run);
        const orders = await getOrder(id, comply);
        const settlement = await getSettlement(id, comply);
        const userInfo = await getUserInfo(access_token, settlement.commercialSpecialistId);
        const totalAmount = await getTotalAmount(id, comply);
        toMail(userInfo, settlement, orders, totalAmount, { path: invoicePath, fileName })
        await run('COMMIT');
        ctx.status = 200;
        ctx.body = 'ok';
    } catch (error) {
        await run('ROLLBACK');
        ctx.status = 500;
        ctx.body = error
        log('---------------------------------------------------')
        console.log(error)
    }
    connection.end();
}

async function update(id, ctx, invoiceFile, run) {
    const body = { ...ctx.request.body, invoiceFile, settlementState: '已开票' };
    const sql = `
        UPDATE settlement SET ${toUpdate(body)}
        WHERE id = ${id}
    `;

    const result = await run(sql);
    if (result.err) {
        throw result.err
    }
}

/** 移动文件 */
async function rename(filePath, fileName) {
    try {
        if (!fileName) return;

        const files = '../../../../../../files';
        const newPath = getNewPath();
        await execSync(`mkdir -p ${path.join(__dirname, files, newPath)}`);
        fs.renameSync(filePath, path.join(__dirname, files, newPath, fileName))
        return newPath + '/' + fileName;
    } catch (error) {
        log('---------------------------------------------------');
        console.log(error)
    }
}

/** 发送邮件 */
async function toMail(userInfo, settlement, orders, totalAmount, attachments) {
    if (!userInfo.email) {
        throw { status: 504, err: { sqlMessage: '邮件发送失败，请联系管理员设置企业邮箱' } }
    }

    const attachmentsPath = path.join(__dirname, '../../../../../../files', attachments.path);
    await sendMail({
        to: `${userInfo.name}<${userInfo.email}>`,
        cc: `李川<lichuan@firemonkeysoft.com>,Yellen<yellen@firemonkeysoft.com>,高娥<gaoe@firemonkeysoft.com>`,
        subject: `【发票已开】【${orders[0].clientName}】【${[...new Set(orders.map(e => e.project))].join('、')}】【${settlement.invoiceNo}】金额：${formatMoney(totalAmount, '')}元`,
        html: `<div>
            <p>发票已开，详见附件</p>
            <p>发票号码：${settlement.invoiceNo}</p>
            <p>金额：${formatMoney(totalAmount, '')}元</p>
            <p>项目：${[...new Set(orders.map(e => e.project))].join('、')}</p>
            <p>订单明细：<br/>${[...new Set(orders.map(e => e.details))].join('<br/>')}</p>
        </div>`,
        attachments: {
            filename: attachments.fileName,
            path: attachmentsPath,
        },
    })
}

/** 获取订单数据 */
async function getOrder(id, comply) {
    return await comply(`
        SELECT o.*, s.unsettlementAmount, c.clientName
        FROM settlementEntry as s
        LEFT JOIN orders AS o ON s.ordersId = o.id
        LEFT JOIN client AS c ON c.id = o.clientId
        WHERE s.settlementId = ${id}
    `)
}

/** 获取结算总金额 */
async function getTotalAmount(id, comply) {
    const data = await comply(`
        SELECT sum(s.unsettlementAmount) as total
        FROM settlementEntry as s
        LEFT JOIN orders AS o ON s.ordersId = o.id
        WHERE s.settlementId = ${id}
    `)
    return data[0].total
}

/** 获取用户数据 */
function getUserInfo(access_token, userid) {
    return new Promise((resolve, reject) => {
        superagent.post('https://oapi.dingtalk.com/topapi/v2/user/get')
            .query({ access_token })
            .send({ userid })
            .end((error, res) => {
                try {
                    if (error) throw error;
                    if (res.body.errcode !== 0) throw res.body
                    resolve(res.body.result);
                } catch (error) {
                    reject({ status: 504, error, sqlMessage: '没有找到员工数据,请切换公司' })
                    // reject({ status: 504, err: error })
                }
            })
    })
}

/** 获取结算单 */
async function getSettlement(id, comply) {
    return (await comply(`
        SELECT s.*
        FROM settlement AS s
        WHERE id = ${id}
    `))[0];
}

/** 获取一个新路径 */
function getNewPath() {
    return path.join(moment().format('YYYY_MM'), 'invoice', v4());
}

/** 执行 sh 脚本 */
function execSync(command) {
    return new Promise(resolve => {
        process.exec(command, resolve)
    })
}